#include <chrono>
#include <memory>

#include "DBoW2/FORB.h"
#include "DBoW2/TemplatedVocabulary.h"

typedef DBoW2::TemplatedVocabulary<DBoW2::FORB::TDescriptor, DBoW2::FORB> ORBVocabulary;

class Timer {
public:
  Timer() {
    start_ = std::chrono::system_clock::now();
  }
  virtual ~Timer() = default;

  double getMilliSec() {
    const auto dur = std::chrono::system_clock::now() - start_;
    const auto msec = std::chrono::duration_cast<std::chrono::milliseconds>(dur).count();
    return msec;
  }

private:
  std::chrono::system_clock::time_point start_;
};

void loadAsText(const std::unique_ptr<ORBVocabulary>& vocab, const std::string& in_file) {
  Timer t;
  vocab->loadFromTextFile(in_file);
  printf("Loading from text: %.0fms\n", t.getMilliSec());
}

void loadAsBinary(const std::unique_ptr<ORBVocabulary>& vocab, const std::string& in_file) {
  Timer t;
  vocab->loadFromBinaryFile(in_file);
  printf("Loading from binary: %.0fms\n", t.getMilliSec());
}

void saveAsText(const std::unique_ptr<ORBVocabulary>& vocab, const std::string& out_file) {
  Timer t;
  vocab->saveToTextFile(out_file);
  printf("Saving as text: %.0fms\n", t.getMilliSec());
}

void saveAsBinary(const std::unique_ptr<ORBVocabulary>& vocab, const std::string& out_file) {
  Timer t;
  vocab->saveToBinaryFile(out_file);
  printf("Saving as binary: %.0fms\n", t.getMilliSec());
}

void showUsage(char **argv) {
  std::cout << "Usage:" << std::endl;
  std::cout << argv[0] << " "
            << "INPUT_TYPE:(txt|bin) "
            << "OUTPUT_TYPE:(txt|bin) "
            << "INPUT_FILEPATH "
            << "OUTPUT_FILEPATH"
            << std::endl;
}

int main(int argc, char **argv) {

  std::string in_file = "/home/xyt/pro/dobw2/bin/vocabulary.yml";
  std::string out_file = "/home/xyt/pro/dobw2/bin/vocabulary.bin";

  std::cout << "INPUT("  << "): " << in_file << std::endl;
  std::cout << "OUTPUT(" << "): " << out_file << std::endl;
 
  ORBVocabulary vocab(in_file);

  //loadAsText(vocab, in_file);
  std::cout << "load finish !!" << std::endl;
  vocab.saveToBinaryFile(out_file);
  //saveAsBinary(vocab, out_file);
  std::cout << "save finish !!" << std::endl;

  return 0;
}
